package com.changge.common.limit.aspect;

import com.changge.common.limit.LimitManager;
import com.changge.common.limit.annotation.AccessLimit;
import com.changge.common.limit.condition.LimitAspectCondition;
import com.changge.common.limit.exception.LimitErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * 自定义限流切面
 *
 * @author zhangrongkang
 * @since 2024/2/18
 */
@Slf4j
@Aspect
@Component
@Conditional(LimitAspectCondition.class)
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AccessLimitAspect {

    @Autowired
    private LimitManager limitManager;

    @Pointcut("@annotation(com.changge.common.limit.annotation.AccessLimit)")
    public void access() {}

    @Before("access()")
    public void accessLimit(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);
        // 如果限流注解不为空
        if (Objects.nonNull(accessLimit)) {
            if (!limitManager.tryAccess(accessLimit)) {
                log.error("接口 {} 限流", accessLimit.key());
                // 抛出限流异常
                throw LimitErrorCode.REQUEST_COUNT_EXCEED_LIMIT.exception();
            }
        }
    }

}
